<?php

class Marcador {
	
	private static $elementos_ignorar = array(".", ",", "?", "!", "\r", "\n", "'", "-", "_", "\"");
	
	private static function qtd_ignorados($string) {
		$quantidade = 0;
		foreach (self::$elementos_ignorar as $elemento) {
			if (mb_stripos($string, $elemento, 0) !== false) {
				// echo "encontrou <textarea>$elemento</textarea>, de ".mb_strlen($elemento)." caracteres., ".mb_substr_count($string, $elemento)." vezes.<br/>";
				$quantidade += mb_substr_count($string, $elemento) * mb_strlen($elemento);
			}
		}
		preg_match_all("/ *\<br\/\>| *<br>| *<br \/\>/", $string, $matches);
		// echo "<textarea>".print_r($matches, true)."</textarea>";
		foreach ($matches[0] as $match) {
			// echo "encontrou <textarea>$match</textarea>, de ".mb_strlen($match)." caracteres.<br/>";
			$quantidade += mb_strlen($match);
		}
		return $quantidade;
	}
	
	private static function posicoes_ignorados($string) {
		$tamanho_string = mb_strlen($string);
		$posicoes = array();
		foreach (self::$elementos_ignorar as $elemento) {
			$tamanho_elemento = mb_strlen($elemento);
			$posicao = mb_stripos($string, $elemento, 0);
			while ($posicao !== false) {
				for ($i = 0; $i < $tamanho_elemento; $i++) {
					$posicao += $i;
					$posicoes[] = $posicao;
				}
				$posicao = mb_stripos($string, $elemento, $posicao + 1);
			}
		}
		natcasesort($posicoes);
		return $posicoes;
	}
	
	private static function remover_ignorados($string) {
		$string = preg_replace("/ *\<br\/\>| *<br>| *<br \/\>/", " ", $string);
		$string = preg_replace("/ +/", " ", $string);
		$string = preg_replace('/[\.\,\?\!\\r\\n"\'\-_]/u', '', $string);
		return $string;
	}
	
	private static function adicionar_espaco_tag($string) {
		$string = preg_replace("/\<br\/\>|<br>|<br \/\>/", "<br/> ", $string);
		return $string;
	}
	
	private static function limpar_acentos($string, $posicao_inicial = 0, $tamanho = null) {
		if ($tamanho == null) {
			$tamanho = mb_strlen($string);
		}
		$string = preg_replace('/[aàáâãåäæ]/iu', 'a', $string);
		$string = preg_replace('/[eèéêë]/iu', 'e', $string);
		$string = preg_replace('/[iìíîï]/iu', 'i', $string);
		$string = preg_replace('/[oòóôõöø]/iu', 'o', $string);
		$string = preg_replace('/[uùúûü]/iu', 'u', $string);
		$string = preg_replace('/[ç]/iu', 'c', $string);
		return mb_convert_case(mb_substr($string, $posicao_inicial, $tamanho), MB_CASE_LOWER);
	}

	private static function imprimir_tabela_caracteres($string) {
		// echo "<table border=\"1\">";
		// echo "<tr>";
		for ($i = 0; $i < mb_strlen($string); $i++) {
			// echo "<td align=\"center\">$i</td>";
		}
		// echo "</tr>";
		// echo "<tr>";
		for ($i = 0; $i < mb_strlen($string); $i++) {
			// echo "<td align=\"center\">".mb_substr($string, $i, 1)."</td>";
		}
		// echo "</tr>";
		// echo "</table>";
	}
	
	public static function marcar_varias($palavras, $haystack, $classe_css) {
		foreach ($palavras as $palavra) {
			$haystack = self::marcar($palavra, $haystack, $classe_css);
		}
		return $haystack;
	}
	
	static function marcar($needle, $haystack, $classe_css) {
		mb_internal_encoding('UTF-8');

		$needle = self::limpar_acentos($needle);
		$haystack = self::adicionar_espaco_tag($haystack);
		
		$haystack_sem_acentos = self::limpar_acentos($haystack);
		$haystack_sem_ignorados = mb_convert_case(self::remover_ignorados($haystack_sem_acentos), MB_CASE_LOWER);
		
		// echo "Needle: <br/>";
		// echo self::imprimir_tabela_caracteres($needle);
		// echo "Haystack: <br/>";
		// echo self::imprimir_tabela_caracteres($haystack);
		// echo "Haystack_sem_acentos: <br/>";
		// echo self::imprimir_tabela_caracteres($haystack_sem_acentos);
		// echo "Haystack_sem_ignorados: <br/>";
		// echo self::imprimir_tabela_caracteres($haystack_sem_ignorados);
		// echo "<p/>";
		
		$tamanho_needle = mb_strlen($needle);
		$tamanho_haystack = mb_strlen($haystack);
		
		if ($tamanho_needle > $tamanho_haystack || $tamanho_needle == 0) {
			return $haystack;
		}
		
		$resultado = "";
		$xf_com_ignorados = 0;
		$qtd_ignorados = 0;
		$posicao = mb_stripos($haystack_sem_acentos, mb_substr($needle, 0, 1), null);
		while ($posicao !== false) {
			// echo "posicao: $posicao<br/>";
			$pedaco_ate_aqui = mb_substr($haystack, 0, $posicao);
			// echo "pedaco_ate_aqui:<br/>";
			self::imprimir_tabela_caracteres($pedaco_ate_aqui);
			$qtd_ignorados_ate_aqui = self::qtd_ignorados($pedaco_ate_aqui);
			// echo "qtd_ignorados_ate_aqui: $qtd_ignorados_ate_aqui<br/>";
			$x0_sem_ignorados = $posicao - $qtd_ignorados_ate_aqui;
			$pedaco_a_comparar = mb_substr($haystack_sem_ignorados, $x0_sem_ignorados, $tamanho_needle);
			// echo "pedaco_a_comparar: $pedaco_a_comparar<br/>";
			if (mb_stripos($pedaco_a_comparar, $needle, 0) === 0) {
				// echo "eh igual a needle<br/>";
				$pedaco_antes = mb_substr($haystack, $xf_com_ignorados, $posicao - $xf_com_ignorados);
				$resultado .= $pedaco_antes;
				
				$indice_needle = 0;
				$deslocamento = 0;
				while ($indice_needle < $tamanho_needle) {
					// echo "indice_needle: $indice_needle<br/>";
					// echo "deslocamento: $deslocamento<br/>";
					// echo "posicao + deslocamento: ".($posicao + $deslocamento)."<br/>";
					if (isset($haystack[$posicao + $deslocamento])) {
						$caractere_haystack = self::limpar_acentos($haystack, $posicao + $deslocamento, 1);
						$caractere_needle = self::limpar_acentos($needle, $indice_needle, 1);
						// echo "caractere_haystack: \"$caractere_haystack\"<br/>";
						// echo "caractere_needle: \"$caractere_needle\"<br/>";
						if ($caractere_needle == $caractere_haystack) {
							// echo "sao iguais<br/>";
							$indice_needle++;							
						}
					}
					else {
						// echo "não são iguais<br/>";
						break;
					}
					$deslocamento++;
				}
				$pedaco_marcado = mb_substr($haystack, $posicao, $deslocamento);
				$xf_com_ignorados = $posicao + $deslocamento;
				$resultado .= "<span class=\"$classe_css\">".$pedaco_marcado."</span>";
				$nova_posicao = $xf_com_ignorados;
			}
			else {
				// echo "Não é igual a needle<br/>";
				$nova_posicao = $posicao + 1;
			}
			if ($nova_posicao <= $tamanho_haystack) {
				$posicao = mb_stripos($haystack, mb_substr($needle, 0, 1), $nova_posicao);
			}
			else {
				$posicao = false;
			}
			// echo "<p/>";
		}
		$pedaco_final = mb_substr($haystack, $xf_com_ignorados, $tamanho_haystack);
		$resultado .= $pedaco_final;
		return $resultado;
	}
	
	static function marcar_musica($musicas, $classe_css, $musica_id = null) {
		$string = "";
		foreach ($musicas as $elemento) {
			if (is_string($elemento)) {
				$string .= $elemento."<br/>";
			}
			else {
				if ($musica_id != null && $elemento->get_id() == $musica_id) {
					$string .= "<span class=\"$classe_css\">".$elemento->get_titulo()."</span><br/>";
				}
				else {
					$string .= $elemento->get_titulo()."<br/>";
				}
			}
		}
		return $string;
	}
}
?>